package com.hoperun.nocserver.modules.base.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;

import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Component;

import com.mongodb.DB;
import com.mongodb.DBObject;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import com.mongodb.gridfs.GridFSInputFile;

/**
 * Service 基类
 * 
 * @author zhu_longxiang
 *
 */
@Component
public class BaseService {
	private static final Log LOGGER = Logs.get();

	@Autowired
	MongoTemplate mongoTemplate;

	/**
	 * 往mongo中保存文件（无metadata）
	 * 
	 * @param collectionName
	 *            集合名称（一般就用fs）
	 * @param file
	 *            文件对象
	 * @param filename
	 *            文件名
	 */
	public void saveFile(String collectionName, File file, String filename) {
		saveFile(collectionName, file, filename, null);
	}

	/**
	 * 往mongo中保存文件（有metadata）
	 * <p>
	 * 逻辑： 先查看数据库中有没有这个文件（根据文件名），如果有，先删除，后插入；反之直接插入。
	 * 
	 * @param collectionName
	 *            集合名称（一般就用fs）
	 * @param file
	 *            文件对象
	 * @param filename
	 *            文件名
	 * @param metadata
	 *            你想存储的信息
	 */
	public void saveFile(String collectionName, File file, String filename, DBObject metadata) {
		try {
			if (Strings.isBlank(filename))
				filename = file.getName();
			DB db = mongoTemplate.getDb();
			// 存储fs的根节点
			GridFS gridFS = new GridFS(db, collectionName);
			GridFSDBFile dbFile = retrieveFileOne(gridFS, filename);
			if (dbFile != null)
				removeFileOne(gridFS, filename);
			GridFSInputFile gfs = gridFS.createFile(file);
			gfs.put("filename", filename);
			gfs.put("contentType", filename.substring(filename.lastIndexOf(".") + 1));
			gfs.put("metadata", metadata);
			gfs.save();
		} catch (Exception e) {
			LOGGER.error("存储文件时发生错误！！！", e);
		}
	}

	/**
	 * 根据集合名和文件名从mongo中读取文件信息
	 * 
	 * @param collectionName
	 *            集合名称（一般就用fs）
	 * @param filename
	 *            文件名称
	 * @return 文件信息
	 */
	public GridFSDBFile retrieveFileOne(String collectionName, String filename) {
		try {
			DB db = mongoTemplate.getDb();
			// 获取fs的根节点
			GridFS gridFS = new GridFS(db, collectionName);
			return gridFS.findOne(filename);
		} catch (Exception e) {
			LOGGER.error("取出文件时发生错误！！！", e);
		}
		return null;
	}

	/**
	 * 根据集合名和文件名从mongo中读取文件信息
	 * 
	 * @param gridFS
	 *            gridFS操作对象
	 * @param filename
	 *            文件名称
	 * @return 文件信息
	 */
	public GridFSDBFile retrieveFileOne(GridFS gridFS, String filename) {
		try {
			return gridFS.findOne(filename);
		} catch (Exception e) {
			LOGGER.error("取出文件时发生错误！！！", e);
		}
		return null;
	}

	/**
	 * 从mongo中移除文件
	 * 
	 * @param collectionName
	 *            集合名称（一般就用fs）
	 * @param filename
	 *            文件名称
	 */
	public void removeFileOne(String collectionName, String filename) {
		DB db = mongoTemplate.getDb();
		GridFS gridFS = new GridFS(db, collectionName);
		gridFS.remove(filename);
	}

	/**
	 * 从mongo中移除文件
	 * 
	 * @param gridFS
	 *            gridFS操作对象
	 * @param filename
	 *            文件名称
	 */
	public void removeFileOne(GridFS gridFS, String filename) {
		gridFS.remove(filename);
	}

	/**
	 * 根据集合名称获取文件（无条件）
	 * 
	 * @param collectionName
	 *            集合名称（一般就用fs）
	 * @return 文件信息集合
	 */
	public List<GridFSDBFile> getFileList(String collectionName) {
		return getFileList(null, collectionName);
	}

	/**
	 * 根据集合名称获取文件（有条件）
	 * 
	 * @param query
	 *            条件对象
	 * @param collectionName
	 *            集合名称（一般就用fs）
	 * @return 文件信息集合
	 */
	public List<GridFSDBFile> getFileList(DBObject query, String collectionName) {
		DB db = mongoTemplate.getDb();
		GridFS gridFS = new GridFS(db, collectionName);
		return gridFS.find(query);
	}

	/**
	 * 根据集合名称获取文件（有条件）
	 * 
	 * @param query
	 *            条件对象
	 * @param gridFS
	 *            gridFS操作对象
	 * @return 文件信息集合
	 */
	public List<GridFSDBFile> getFileList(DBObject query, GridFS gridFS) {
		return gridFS.find(query);
	}

	/**
	 * 根据集合名称获取文件（无条件）
	 * 
	 * @param gridFS
	 *            gridFS操作对象
	 * @return 文件信息集合
	 */
	public List<GridFSDBFile> getFileList(GridFS gridFS) {
		return getFileList(null, gridFS);
	}

	/**
	 * 将mongo存储文件下载
	 * 
	 * @param out
	 *            输出流
	 * @param gfsFile
	 *            文件对象
	 */
	public void writeToOutputStream(OutputStream out, GridFSDBFile gfsFile) {
		try {
			gfsFile.writeTo(out);
		} catch (IOException e) {
			LOGGER.error("输出文件错误！", e);
		}
	}

	/**
	 * 将mongo存储文件下载
	 * 
	 * @param filename
	 *            输出的文件路径
	 * @param gfsFile
	 *            文件对象
	 */
	public void writeToOutputStream(String filename, GridFSDBFile gfsFile) {
		try {
			OutputStream out = new FileOutputStream(new File(filename));
			gfsFile.writeTo(out);
		} catch (IOException e) {
			LOGGER.error("输出文件错误！", e);
		}
	}

}
